<template>
  <div class="course-video">
    <el-card>
      <div slot="header">
        课程相关信息
      </div>
      <el-form>
        <el-form-item label="视频上传">
          <input ref="video-file" type="file">
        </el-form-item>
        <el-form-item label="封面上传">
          <input ref="image-file" type="file">
        </el-form-item>
        <el-form-item>
          <el-button type="primary"
            @click="handleUpload"
          >开始上传</el-button>
          <el-button @click="$router.push({
            name: 'course-section',
            params: {
              courseId
            }
          })">返回</el-button>
        </el-form-item>
        <el-form-item>
          <p v-if="uploadPercent !== 0">视频上传中：{{ uploadPercent }}%</p>
          <p v-if="isUploadSuccess">视频转码中：{{ isTranscodeSuccess ? '完成' : '正在转码，请稍后...' }} </p>
        </el-form-item>
      </el-form>
    </el-card>
  </div>
</template>

<script>
import {
  aliyunImageUploadAddressAndAuth,
  aliyunVideoUploadAddressAndAuth,
  aliyunVideoTrancode,
  getAliyunTranscodePercent
} from '@/services/aliyun-upload'

export default {
  name: 'CourseVideo',
  props: {
    courseId: {
      type: [String, Number],
      required: true
    }
  },
  data () {
    return {
      uploader: null,
      imageURl: '',
      videoId: null,
      uploadPercent: 0,
      isUploadSuccess: false,
      isTranscodeSuccess: false
    }
  },
  created () {
    this.initUploader()
  },
  methods: {
    // 初始化上传对象
    initUploader () {
      // 官方示例：声明 AliyunUpload.Vod 初始化回调。
      this.uploader = new window.AliyunUpload.Vod({
        // 阿里账号ID，必须有值
        userId: '1618139964448548',
        // 上传到视频点播的地域，默认值为'cn-shanghai'，//eu-central-1，ap-southeast-1
        region: '',
        // 分片大小默认1 MB，不能小于100 KB
        partSize: 1048576,
        // 并行上传分片个数，默认5
        parallel: 5,
        // 网络原因失败时，重新上传次数，默认为3
        retryCount: 3,
        // 网络原因失败时，重新上传间隔时间，默认为2秒
        retryDuration: 2,
        // 开始上传
        onUploadstarted: function (uploadInfo) {
          console.log('onUploadstarted', uploadInfo)
        },
        // 文件上传成功
        onUploadSucceed: function (uploadInfo) {
          console.log('onUploadSucceed', uploadInfo)
        },
        // 文件上传失败
        onUploadFailed: function (uploadInfo, code, message) {
          console.log('onUploadFailed', uploadInfo, code, message)
        },
        // 文件上传进度，单位：字节
        onUploadProgress: function (uploadInfo, totalSize, loadedPercent) {
          console.log('onUploadProgress', uploadInfo, totalSize, loadedPercent)
        },
        // 上传凭证超时
        onUploadTokenExpired: function (uploadInfo) {
          console.log('onUploadTokenExpired', uploadInfo)
        },
        // 全部文件上传结束
        onUploadEnd: function (uploadInfo) {
          console.log('onUploadEnd', uploadInfo)
        }
      })
    },
    handleUpload () {
      // 点击上传时重置状态信息
      this.isTranscodeSuccess = false
      this.isUploadSuccess = false
      this.uploadPercent = 0
      const videoFile = this.$refs['video-file'].files[0]
      const imageFile = this.$refs['image-file'].files[0]
      // 将文件添加到上传列表
      const uploader = this.uploader
      //  - 文档示例：uploader.addFile(event.target.files[i], null, null, null, paramData)
      uploader.addFile(imageFile)
      uploader.addFile(videoFile)
      // 开始上传
      //  - 开始上传后，上面的文件回按添加的顺序依次上传
      //  - 这时会触发 onUploadStarted 事件
      uploader.startUpload()
    },
    // 开始上传（uploader.startUpload() 触发后执行该回调）
    //   - 将回调更改为箭头函数，以便在内部通过 this 操作 Vue 实例
    onUploadstarted: async uploadInfo => {
      // 一、获取凭证
      // console.log(uploadInfo)
      // 1. 声明变量存储得到上传凭证
      let uploadAddressAndAuth = null
      // 2. 根据 isImage 检测上传文件类型
      if (uploadInfo.isImage) {
        const { data } = await aliyunImageUploadAddressAndAuth()
        if (data.code === '000000') {
          // 3. data.data 即为凭证信息组成的对象
          uploadAddressAndAuth = data.data
          // 5. 保存图片地址，给视频接口使用
          this.imageURL = uploadAddressAndAuth.imageURL
        }
      } else {
        // 4. 观察 uploadInfo 数据，根据请求参数名设置参数
        //   - 由于视频接口要求传入封面图片地址 imageUrl，所以必须先发图再发视频（后端
        //     - 先将图片数据存储给 this，便于视频接口使用
        const { data } = await aliyunVideoUploadAddressAndAuth({
          fileName: uploadInfo.file.name,
          imageUrl: this.imageURL
        })
        if (data.code === '000000') {
          // 6. 存储凭证
          //  - 图片与视频上传的区别在于图片存在 imageId，视频为 videoId，其他相同
          uploadAddressAndAuth = data.data
          this.videoId = data.data.videoId
        }
      }
      // 二、设置凭证
      this.uploader.setUploadAuthAndAddress(
        uploadInfo,
        uploadAddressAndAuth.uploadAuth,
        uploadAddressAndAuth.uploadAddress,
        uploadAddressAndAuth.imageId || uploadAddressAndAuth.videoId
      )
      // 设置完毕，上传进度开始执行
    },
    // 文件上传进度，单位：字节
    //   - 修改为箭头函数，内部 this 才能访问 Vue 实例
    onUploadProgress: (uploadInfo, totalSize, loadedPercent) => {
      console.log('onUploadProgress', uploadInfo, totalSize, loadedPercent)
      // 只对视频上传进度进行监测即可
      if (!uploadInfo.isImage) {
        this.uploadPercent = Math.floor(loadedPercent * 100)
      }
    },
    // 全部文件上传结束
    onUploadEnd: async uploadInfo => {
      this.isUploadSuccess = true
      // 调用接口
      const { data } = await aliyunVideoTrancode({
        lessonId: this.$route.query.lessonId,
        coverImageUrl: this.imageURL,
        fileName: this.$refs['video-file'].files[0].name,
        fileId: this.videoId
      })
      if (data.code === '000000') {
        // 转码开始后，需要轮询转码进度
        const timer = setInterval(async () => {
          const { data } = getAliyunTranscodePercent(this.$route.query.lessonId)
          if (data === 100) {
            this.isTranscodeSuccess = true
            // 当上传进度为 100，停止定时器，并进行提示
            clearInterval(timer)
            this.$message.success('转码成功')
          }
        }, 1000)
      }
    }
  }
}
</script>

<style lang="scss" scoped></style>
